package com.example.airhockey2

import android.content.Context
import android.opengl.GLES20.*
import android.opengl.GLSurfaceView
import android.util.Log
import com.example.airhockey2.helper.ShaderHelper
import com.example.airhockey2.utils.LoggerConfig
import com.example.airhockey2.utils.OpenGLUtils
import java.nio.ByteBuffer
import java.nio.ByteOrder
import java.nio.FloatBuffer
import javax.microedition.khronos.egl.EGLConfig
import javax.microedition.khronos.opengles.GL10

/**
 *  @author : BuildF
 *  date : 2020/7/9 15:56
 *  description :
 */
class AirHockeyRenderer constructor(context: Context) :
    GLSurfaceView.Renderer {
    private val A_POSITION = "a_Position"
    private val A_COLOR = "a_Color"
    private val POSITION_COMPONENT_COUNT = 2
    private val COLOR_COMPONENT_COUNT = 3
    private val BYTES_PER_FLOAT = 4
    private val STRIDE = (POSITION_COMPONENT_COUNT + COLOR_COMPONENT_COUNT) * BYTES_PER_FLOAT
    private var vertexData: FloatBuffer? = null
    private val context: Context by lazy { context }
    private var program = 0
    private var aPositionLocation = 0
    private var aColorLocation = 0


    init {
        val tableVerticesWithTriangles: FloatArray = floatArrayOf(
            // Order of coordinates: X, Y, R, G, B

            // Triangle Fan
            0.0f, 0.0f, 1.0f, 1.0f, 1.0f,
            -0.5f, -0.5f, 0.7f, 0.7f, 0.7f,
            0.5f, -0.5f, 0.7f, 0.7f, 0.7f,
            0.5f, 0.5f, 0.7f, 0.7f, 0.7f,
            -0.5f, 0.5f, 0.7f, 0.7f, 0.7f,
            -0.5f, -0.5f, 0.7f, 0.7f, 0.7f,

            // Line 1
            -0.5f, 0f, 1.0f, 0.0f, 0.0f,
            0.5f, 0.0f, 1.0f, 0.0f, 0.0f,

            // Mallets
            0.0f, -0.25f, 0.0f, 0.0f, 1.0f,
            0.0f, 0.25f, 1.0f, 0.0f, 0.0f

        )
        vertexData =
                //分配一块本地内存，这块内存不会被垃圾回收器管理，
            ByteBuffer.allocateDirect(tableVerticesWithTriangles.size * BYTES_PER_FLOAT)
                //按照本地字节序排列
                .order(ByteOrder.nativeOrder())
                //转回成浮点型实例
                .asFloatBuffer()

        //将数据从内存复制到刚分配的本地内存
        vertexData?.put(tableVerticesWithTriangles)
    }

    override fun onDrawFrame(glUnused: GL10?) {
        // Clear the rendering surface.
        glClear(GL_COLOR_BUFFER_BIT)

        // Draw the table.
        glDrawArrays(GL_TRIANGLE_FAN, 0, 6)

        // Draw the center dividing line.
        glDrawArrays(GL_LINES, 6, 2)

        // Draw the first mallet.
        glDrawArrays(GL_POINTS, 8, 1)

        // Draw the second mallet.
        glDrawArrays(GL_POINTS, 9, 1)
    }

    override fun onSurfaceChanged(p0: GL10?, width: Int, height: Int) {
        Log.d("ljy", "onSurfaceChanged")
        glViewport(0, 0, width, height)
    }


    override fun onSurfaceCreated(p0: GL10?, p1: EGLConfig?) {
        glClearColor(0.0f, 0.0f, 0.0f, 0.0f)
        val vertexShaderSource =
            OpenGLUtils.getShaderFromAssets(
                context, "simple_vertex_shader.glsl"
            )
        val fragmentShaderSource =
            OpenGLUtils.getShaderFromAssets(
                context, "simple_fragment_shader.glsl"
            )
        val vertexShader =
            ShaderHelper.compileVertexShader(vertexShaderSource)
        val fragmentShader = ShaderHelper
            .compileFragmentShader(fragmentShaderSource)
        program =
            ShaderHelper.linkProgram(vertexShader, fragmentShader)
        if (LoggerConfig.ON) {
            ShaderHelper.validateProgram(program)
        }
        //在绘制任何东西到屏幕上面都要使用这里定义的程序
        glUseProgram(program)

        aPositionLocation = glGetAttribLocation(program, A_POSITION)
        aColorLocation = glGetAttribLocation(program, A_COLOR)

        //设置初始读取位置为0

        // Bind our data, specified by the variable vertexData, to the vertex
        // attribute at location A_POSITION_LOCATION.
        vertexData!!.position(0)
        glVertexAttribPointer(
            aPositionLocation, POSITION_COMPONENT_COUNT, GL_FLOAT,
            false, STRIDE, vertexData
        )

        glEnableVertexAttribArray(aPositionLocation)

        // Bind our data, specified by the variable vertexData, to the vertex
        // attribute at location A_COLOR_LOCATION.
        vertexData!!.position(POSITION_COMPONENT_COUNT)
        glVertexAttribPointer(
            aColorLocation, COLOR_COMPONENT_COUNT, GL_FLOAT,
            false, STRIDE, vertexData
        )

        glEnableVertexAttribArray(aColorLocation)

    }
}